package cn.tedu.tmall.passport.service.impl;

import cn.tedu.common.enumerator.ServiceCode;
import cn.tedu.common.ex.ServiceException;
import cn.tedu.common.pojo.authentication.CurrentPrincipal;
import cn.tedu.common.pojo.po.UserStatePO;
import cn.tedu.tmall.passport.dao.cache.IUserCacheRepository;
import cn.tedu.tmall.passport.dao.persist.repository.IAdminRepository;
import cn.tedu.tmall.passport.pojo.entity.Admin;
import cn.tedu.tmall.passport.pojo.param.*;
import cn.tedu.tmall.passport.pojo.vo.*;
import cn.tedu.tmall.passport.service.IAdminService;
import com.alibaba.fastjson.JSON;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
@Service
public class AdminServiceImpl implements IAdminService {

    @Value("${tmall.jwt.secret-key}")
    private   String secretKey;
    @Autowired
    private PasswordEncoder passwordEncoder;
    @Autowired
    private IAdminRepository adminRepository;
    @Autowired
    private IUserCacheRepository userCacheRepository;


    //用户注册
    @Override
    public int AdminReg(AdminRegParam adminRegParam) {
//        String phone = staffRegParam.getPhone();
//        LoginInfoVO infoByPhone = userRepository.getInfoByPhone(phone);
        /*根据名字查看用户是否存在*/
        AdminLoginInfoVO adminInfo = adminRepository.getLoginInfoByUsername(adminRegParam.getUsername());
        if(adminInfo!=null){
            String message ="用户名已存在";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERROR_UNKNOWN,message);
        }
        /*注册用户*/
        Admin admin = new Admin();

        admin.setEnable(1);
//        user.setRole(1L);
        BeanUtils.copyProperties(adminRegParam,admin);
//        user.setAvatar("/img/defaultAvatar.png");
        admin.setPassword(passwordEncoder.encode(adminRegParam.getPassword()));
        return adminRepository.adminReg(admin);

    }


    @Override
    public AdminLoginResultVO login(AdminLoginInfoParam adminLoginInfoParam, String remoteAddr, String userAgent) {
        String username = adminLoginInfoParam.getUsername();
        AdminLoginInfoVO loginInfo = adminRepository.getLoginInfoByUsername(username);
        if (loginInfo == null) {
            String message = "登录失败，用户名或密码错误！";
            throw new ServiceException(ServiceCode.ERROR_UNAUTHORIZED, message);
        }

        if (loginInfo.getEnable() != 1) {
            String message = "登录失败，此账号已经被禁用！";
            throw new ServiceException(ServiceCode.ERROR_UNAUTHORIZED_DISABLED, message);
        }

        String password = adminLoginInfoParam.getPassword();
        // if (!loginInfo.getPassword().equals(password)) {
        if (!passwordEncoder.matches(password, loginInfo.getPassword())) {
            String message = "登录失败，用户名或密码错误！";
            throw new ServiceException(ServiceCode.ERROR_UNAUTHORIZED, message);
        }

        // TODO 处理登录日志相关：向登录日志表中插入数据，修改用户表中冗余存储的登录数据

        // 确定当事人
        CurrentPrincipal principal = new CurrentPrincipal();
        principal.setId(loginInfo.getId());
        principal.setUsername(loginInfo.getUsername());

        // 确定权限列表
        List<GrantedAuthority> authorities = new ArrayList<>();
        List<String> permissions = loginInfo.getPermissions();
        for (String permission : permissions) {
            authorities.add(new SimpleGrantedAuthority(permission));
        }

        // 将权限列表和用户状态写入到Redis中
        String authoritiesJsonString = JSON.toJSONString(authorities);
        UserStatePO userStatePO = new UserStatePO();
        userStatePO.setEnable(loginInfo.getEnable());
        userStatePO.setAuthoritiesJsonString(authoritiesJsonString);
        userCacheRepository.saveUserState(loginInfo.getId(), userStatePO);

        // 向SecurityContext中存入Authentication
        // Authentication authentication = new UsernamePasswordAuthenticationToken(
        //        principal, null, authorities);
        // SecurityContext securityContext = SecurityContextHolder.getContext();
        // securityContext.setAuthentication(authentication);

        Map<String, Object> claims = new HashMap<>();
        claims.put("id", loginInfo.getId());
        claims.put("username", loginInfo.getUsername());
        claims.put("remote_addr", remoteAddr);
        claims.put("user_agent", userAgent);

        String jwt = Jwts.builder()
                // Header
                .setHeaderParam("alg", "HS256")
                .setHeaderParam("typ", "JWT")
                // Payload
                .setClaims(claims)
                // Verify Signature
                .signWith(SignatureAlgorithm.HS256, secretKey)
                // 完成
                .compact();

        AdminLoginResultVO loginResult = new AdminLoginResultVO();
        loginResult.setId(loginInfo.getId());
        loginResult.setUsername(loginInfo.getUsername());
        loginResult.setAvatar(loginInfo.getImgUrl());
        loginResult.setToken(jwt);
        loginResult.setAuthorities(permissions);
        return loginResult;
    }

    @Override
    public void logout(CurrentPrincipal currentPrincipal) {
        Long id = currentPrincipal.getId();
        userCacheRepository.deleteUserState(id);
    }

    /*@Override
    public UserLoginResultVO loginByPhone(
            LoginByPhoneParam loginByPhoneParam,
            String remoteAddr , String userAgent) {


        String phone = loginByPhoneParam.getPhone();


        UserLoginInfoVO loginInfo = userRepository.getLoginInfoByPhone(phone);


        if (loginInfo == null) {
            String message = "登录失败，手机号错误！";
            throw new ServiceException(ServiceCode.ERROR_UNAUTHORIZED, message);
        }

        if (loginInfo.getEnable() != 1) {
            String message = "登录失败，此账号已经被禁用！";
            throw new ServiceException(ServiceCode.ERROR_UNAUTHORIZED_DISABLED, message);
        }



        String code = loginByPhoneParam.getCode();


        // 从redis中取出code
        String redisCode = userCacheRepository.getCode(phone);
//         if (!loginInfo.getPassword().equals(password)) {
        if (!code.equals(redisCode)) {
            String message = "登录失败，验证码错误或验证码已失效，请重新获取验证码！";
            throw new ServiceException(ServiceCode.ERROR_UNAUTHORIZED, message);
        }

        // 删除redis中的code
       // userCacheRepository.deleteCode(phone);



        // 确定当事人
        CurrentPrincipal principal = new CurrentPrincipal();

        principal.setId(loginInfo.getId());
        principal.setUsername(loginInfo.getUsername());

        log.info("++++++++++++++++++++"+principal);

        // 确定权限列表
//        List<GrantedAuthority> authorities = new ArrayList<>();
//        List<String> permissions = loginInfo.getPermissions();
//
//        log.info("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"+permissions);
//        log.info("+++++++++++++++++++++++++++++++++++++++++++++++"+loginInfo.getPermissions().toString());
//
//        if (permissions.size()==0){
//            permissions.add("1");
//        }
//        for (String permission : permissions) {
//            authorities.add(new SimpleGrantedAuthority(permission));
//        }

        // 将权限列表和用户状态写入到Redis中
        String authoritiesJsonString = JSON.toJSONString(null);
        UserStatePO userStatePO = new UserStatePO();
        userStatePO.setEnable(loginInfo.getEnable());
        userStatePO.setAuthoritiesJsonString(authoritiesJsonString);
        userCacheRepository.saveUserState(loginInfo.getId(), userStatePO);

        // 向SecurityContext中存入Authentication
         Authentication authentication = new UsernamePasswordAuthenticationToken(
                principal, null, null);
         SecurityContext securityContext = SecurityContextHolder.getContext();
         securityContext.setAuthentication(authentication);

        Map<String, Object> claims = new HashMap<>();
        claims.put("id", loginInfo.getId());
        claims.put("username", loginInfo.getUsername());
        claims.put("remote_addr", remoteAddr);
        claims.put("user_agent", userAgent);

        String jwt = Jwts.builder()
                // Header
                .setHeaderParam("alg", "HS256")
                .setHeaderParam("typ", "JWT")
                // Payload
                .setClaims(claims)
                // Verify Signature
                .signWith(SignatureAlgorithm.HS256, secretKey)
                // 完成
                .compact();

        UserLoginResultVO loginResult = new UserLoginResultVO();
        loginResult.setId(loginInfo.getId());
        loginResult.setUsername(loginInfo.getUsername());
        loginResult.setAvatar(loginInfo.getImgeUrl());
        loginResult.setToken(jwt);
        loginResult.setAuthorities(null);
        return loginResult;
    }*/

    }
